<?php

namespace app\admin\controller\yunfood\shop;

use addons\yunfood\library\Logic;
use addons\yunfood\model\Config;
use addons\yunfood\model\Qrcode;
use addons\yunfood\model\Shop;
use addons\yunfood\library\Super;
use addons\yunfood\model\ImportLog as ImportLogModel;
use app\admin\model\yunfood\ShopDesk;
use addons\yunfood\library\Backend;
use fast\Random;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use think\Exception;

/**
 * 门店 - 桌号
 */
class Desk extends Backend
{
    /**
     * @var ShopDesk
     */
    protected $model;

    // 联表查询，解决字段冲突
    protected $relationSearch = true;

    protected $shopField = 'shop_id';

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new ShopDesk();

        // 关联门店
        $this->view->assign('shopId', $this->shopId);
        $this->assignconfig('shopId', $this->shopId);

        // 门店列表
        $this->view->assign('shopList', Shop::getOptionList());
        $this->assignconfig('shopList', Shop::getOptionList());

        // 类型和状态
        $this->view->assign('statusList', $this->model::getStatusList());
        $this->assignconfig('statusList', $this->model::getStatusList());
    }

    /**
     * 查看
     */
    public function index()
    {
        $sid = $this->request->request('sid');
        $shop = Shop::get($sid);
        if ($this->request->isAjax()) {
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
            // 所属门店
            $where = $this->getShopWhere($where);
            $query = $this->model->with(['shop_data'])->where($where);
            if ($sid) {
                $query->where(['shop_id' => $sid]);
            }
            $list = $query->order($sort, $order)->limit($offset, $limit)->paginate($limit);
            $result = array(
                'total' => $list->total(),
                'rows'  => $list->items(),
            );

            return json($result);
        }

        // 门店ID
        $this->view->assign('sid', $sid);
        $this->assignconfig('sid', $sid);

        return $this->view->fetch(null, ['shop' => $shop]);
    }


    /**
     * 批量生成桌号
     */
    public function generate()
    {
        if ($this->request->isPost()) {
            $params = $this->request->post("row/a");
            if ($params) {
                $this->authToShop($params['shop_id']);

                $counter = [];
                if ($params['start_number'] > $params['end_number'] || $params['start_number'] < 0) {
                    $this->error(__('桌号范围无效'));
                }

                for ($i = $params['start_number']; $i <= $params['end_number']; $i++) {
                    $number = $params['number_prefix'] . $i;
                    if (! ShopDesk::get(['shop_id' => $params['shop_id'], 'number' => $number])) {
                        $shopCode = new ShopDesk();
                        $shopCode->scenario = 'add';
                        $shopCode->shop_id = $params['shop_id'];
                        $shopCode->number = $number;
                        $shopCode->note = $params['note'];
                        $shopCode->status = ShopDesk::STATUS_NORMAL;
                        $shopCode->allowField(true)->save();
                        Super::counter($counter, '新增数据');
                        continue;
                    }
                    Super::counter($counter, '重复数据');
                }

                // 处理结果
                $content = ['处理成功<br>'];
                foreach ($counter as $key => $value) {
                    $hasError = false;
                    if (! in_array($key, ['新增数据', '重复数据'])) {
                        $key .= '，导入失败';
                        $hasError = true;
                    }
                    $cont = $key . '： ' . $value . '条';
                    if ($hasError) {
                        $cont = '<b style="color: yellow;">' . $cont . '</b>';
                    }
                    $content[] = $cont;
                }
                $content = implode('<br>', $content);

                $this->success($content);
            }
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $this->view->assign('row', []);

        return $this->view->fetch();
    }

    /**
     * 数据导入
     *
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
     */
    public function import()
    {
        // 超时、超内存设置
        ini_set('memory_limit', '1024M');
        ini_set('max_execution_time', '0');

        // 获取文件路径
        $file = $this->request->request('file');
        if (! $file) {
            $this->error(__('Parameter %s can not be empty', 'file'));
        }
        $filePath = ROOT_PATH . DS . 'public' . DS . $file;
        if (! is_file($filePath)) {
            $this->error(__('No results were found'));
        }

        // 新增导入结果
        ImportLogModel::create([
            'scene'       => ImportLogModel::SCENE_SHOP_DESK,
            'import_file' => $file,
            'status'      => ImportLogModel::STATUS_HANDLE
        ]);

        // 实例化reader，并读取文件
        $ext = pathinfo($filePath, PATHINFO_EXTENSION);
        if ($ext !== 'xlsx') {
            $this->error(__('Unknown data format'));
        }
        $reader = new Xlsx();
        if (! $spreadsheet = $reader->load($filePath)) {
            $this->error(__('Unknown data format'));
        }
        $currentSheet = $spreadsheet->getSheet(0);  // 读取文件中的第一个工作表
        $allColumn = $currentSheet->getHighestDataColumn();  // 取得最大的列号
        $allRow = $currentSheet->getHighestRow();  // 取得一共有多少行
        $maxColumnNumber = Coordinate::columnIndexFromString($allColumn);  // 取得最大的列数字
        if ($allRow <= 2) {
            $this->error(__('No rows were updated'));
        }
        $firstHead = $currentSheet->getCellByColumnAndRow(1, 2)->getValue();
        if ($firstHead !== '门店') {
            $this->error(__('数据表头不对'));
        }

        $counter = [];
        try {
            // 获取数据
            $dataList = [];
            for ($currentRow = 3; $currentRow <= $allRow; $currentRow++) {
                $values = [];
                for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
                    $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
                    $values[] = is_null($val) ? '' : trim($val);
                }
                $dataList[] = $values;
            }

            // 设置标题
            $this->setSheetCellValue($currentSheet, -1, '导入结果');
            $currentSheet->getCellByColumnAndRow(3, 2)->getStyle()->applyFromArray([
                'font'      => [
                    'name'  => 'Arial',
                    'color' => ['rgb' => '000000'],
                    'size'  => 12,
                    'bold'  => true
                ],
                'alignment' => [
                    'horizontal' => Alignment::HORIZONTAL_CENTER,
                    'vertical'   => Alignment::VERTICAL_CENTER,
                ]
            ]);

            // 处理数据
            // 列对应关系：0=门店，1=桌号，2=备注
            foreach ($dataList as $index => $item) {
                if (empty($item[0])) {
                    $this->setSheetCellValue($currentSheet, $index, '门店不能为空', 1, $counter);
                    continue;
                }
                if (empty($item[1])) {
                    $this->setSheetCellValue($currentSheet, $index, '桌号不能为空', 1, $counter);
                    continue;
                }
                if (! $shop = Shop::get(['name' => $item[0]])) {
                    $this->setSheetCellValue($currentSheet, $index, '门店名称不对', 1, $counter);
                    continue;
                }
                if ($this->shopId && $this->shopId != $shop->id) {
                    $this->setSheetCellValue($currentSheet, $index, '无此门店权限', 1, $counter);
                    continue;
                }
                if (! $shopCode = ShopDesk::get([
                    'shop_id' => $shop->id,
                    'number'  => $item[1],
                ])) {
                    $shopCode = new ShopDesk();
                    $shopCode->scenario = 'add';
                    $shopCode->shop_id = $shop->id;
                    $shopCode->number = $item[1];
                    $shopCode->note = $item[2];
                    $shopCode->status = ShopDesk::STATUS_NORMAL;
                    $shopCode->allowField(true)->save();
                    $this->setSheetCellValue($currentSheet, $index, '新增数据', 0, $counter);
                    continue;
                }
                $shopCode->allowField(true)->save();
                $this->setSheetCellValue($currentSheet, $index, '更新数据', 0, $counter);
            }

            // 生成excel文件
            $filePath = DS . 'uploads' . DS . date('Ymd') . DS . Random::alnum(32) . '.xlsx';
            $objWriter = IOFactory::createWriter($spreadsheet, 'Xlsx');
            $objWriter->save(ROOT_PATH . 'public' . $filePath);

            // 更新导入结果
            ImportLogModel::update([
                'result_file' => $filePath,
                'status'      => ImportLogModel::STATUS_FINISH
            ], [
                'scene'       => ImportLogModel::SCENE_SHOP_DESK,
                'import_file' => $file,
            ]);
        } catch (Exception $exception) {
            $this->error($exception->getMessage());
        }

        // 导入结果
        $content = ['处理成功<br>'];
        foreach ($counter as $key => $value) {
            $hasError = false;
            if (! in_array($key, ['新增数据', '重复数据'])) {
                $key .= '，导入失败';
                $hasError = true;
            }
            $cont = $key . '： ' . $value . '条';
            if ($hasError) {
                $cont = '<b style="color: yellow;">' . $cont . '</b>';
            }
            $content[] = $cont;
        }
        $content = implode('<br>', $content);

        $exportResult = $filePath;
        $content .= '<br><br><a href="' . $exportResult . '" target="_blank" style="color: yellow;"><b><i class="fa fa-download"></i> 下载导入结果</b></a>';

        $this->success($content);
    }

    /**
     * 设置表格内容
     *
     * @param $workSheet
     * @param $index
     * @param $value
     */
    private function setSheetCellValue(&$workSheet, $index, $value, $level = 0, &$counter = [])
    {
        if ($level != -1) {
            Super::counter($counter, $value);
        }
        if ($oldValue = $workSheet->getCellByColumnAndRow(4, $index + 3)->getValue()) {
            $value = $oldValue . '；' . $value;
        }
        $workSheet->setCellValueByColumnAndRow(4, $index + 3, $value);
        if (! $oldValue) {
            $workSheet->getCellByColumnAndRow(4, $index + 3)->getStyle()->applyFromArray([
                'font'      => [
                    'name'  => 'Arial',
                    'color' => ['rgb' => $level > 0 ? 'f75544' : '000000'],
                    'size'  => 12,
                ],
                'alignment' => [
                    'horizontal' => Alignment::HORIZONTAL_CENTER,
                    'vertical'   => Alignment::VERTICAL_CENTER,
                ]
            ]);
        }
    }

    // 导出数据
    public function export()
    {
        // 超时、超内存设置
        ini_set('memory_limit', '1024M');
        ini_set('max_execution_time', '0');

        if ($this->request->isPost()) {
            $search = $this->request->post('search');
            $ids = $this->request->post('ids');
            $filter = $this->request->post('filter');
            $op = $this->request->post('op');
            $columns = $this->request->post('columns');

            // 初始化表
            $spreadsheet = new Spreadsheet();
            $worksheet = $spreadsheet->setActiveSheetIndex(0);
            $worksheet->getDefaultRowDimension()->setRowHeight(25);  // 设置默认行高
            $worksheet->getDefaultColumnDimension()->setAutoSize(true);  // 设置自动宽

            // 设置标题
            foreach (['ID', '门店', '桌号', '备注', '消费金额', '下单次数', '最近下单', '状态', '变更时间', '新增时间'] as $key => $value) {
                $worksheet->setCellValueByColumnAndRow($key + 1, 1, __($value));
                $worksheet->getCellByColumnAndRow($key + 1, 1)->getStyle()->applyFromArray([
                    'font'      => [
                        'name'  => 'Arial',
                        'color' => ['rgb' => '000000'],
                        'size'  => 12,
                        'bold'  => true
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_CENTER,
                        'vertical'   => Alignment::VERTICAL_CENTER,
                    ]
                ]);
            }

            // 获取条件
            $whereIds = $ids === 'all' ? '1=1' : ['id' => ['in', explode(',', $ids)]];
            $this->request->get(['search' => $search, 'ids' => $ids, 'filter' => $filter, 'op' => $op]);
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();

            // 所属门店
            $where = $this->getShopWhere($where);

            // 查询数据
            $row = 1;
            $this->model
                ->where($where)
                ->where($whereIds)
                ->chunk(100, function ($items) use (&$row, &$worksheet) {
                    foreach ($items as $item) {
                        $row++;
                        $col = 1;
                        // 题目
                        $values = Super::arrayGetSet($item, [
                            'id',
                            'shop_name'       => function ($item) {
                                return $item->shopData->name ?? '--';
                            },
                            'number',
                            'note',
                            'cost_amount',
                            'order_count',
                            'last_order_time' => function ($item) {
                                return $item->last_order_time ? date('Y-m-d H:i:s', $item->last_order_time) : '';
                            },
                            'status_text',
                            'updated_at'      => function ($item) {
                                return date('Y-m-d H:i:s', $item->updated_at);
                            },
                            'created_at'      => function ($item) {
                                return date('Y-m-d H:i:s', $item->created_at);
                            }
                        ]);

                        // 其他
                        foreach ($values as $value) {
                            $worksheet->setCellValueByColumnAndRow($col, $row, $value);
                            $worksheet->getStyleByColumnAndRow($col, $row)->getNumberFormat()
                                ->setFormatCode(NumberFormat::FORMAT_TEXT);
                            $worksheet->getCellByColumnAndRow($col, $row)->getStyle()->applyFromArray([
                                'alignment' => [
                                    'horizontal' => Alignment::HORIZONTAL_CENTER,
                                    'vertical'   => Alignment::VERTICAL_CENTER,
                                ]
                            ]);
                            $col++;
                        }
                    }
                });

            // 导出文件
            // Redirect output to a client’s web browser (Excel2007)
            $fileName = date('YmdHis');
            header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
            header('Content-Disposition: attachment;filename="' . $fileName . '.xlsx"');
            header('Cache-Control: max-age=0');
            // If you're serving to IE 9, then the following may be needed
            header('Cache-Control: max-age=1');
            // If you're serving to IE over SSL, then the following may be needed
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');  // always modified
            header('Cache-Control: cache, must-revalidate');  // HTTP/1.1
            header('Pragma: public');  // HTTP/1.0
            $objWriter = IOFactory::createWriter($spreadsheet, 'Xlsx');
            $objWriter->save('php://output');
            exit;
        }
    }

    // 导出二维码
    public function exportQrcode()
    {
        // 超时、超内存设置
        ini_set('memory_limit', '2048M');
        ini_set('max_execution_time', '0');

        if ($this->request->isPost()) {
            $search = $this->request->post('search');
            $ids = $this->request->post('ids');
            $filter = $this->request->post('filter');
            $op = $this->request->post('op');
            $columns = $this->request->post('columns');

            $appId = Config::getGroupAttribute(Config::GROUP_BASE, 'app_id');
            $appSecret = Config::getGroupAttribute(Config::GROUP_BASE, 'app_secret');
            $h5Domain = Config::getH5Domain();
            if ((! $appId || ! $appSecret) && ! $h5Domain) {
                $this->error(__('小程序Appid和H5域名至少需要配置一种'));
            }

            // 获取条件
            $whereIds = $ids === 'all' ? '1=1' : ['id' => ['in', explode(',', $ids)]];
            $this->request->get(['search' => $search, 'ids' => $ids, 'filter' => $filter, 'op' => $op]);
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();

            // 所属门店
            $where = $this->getShopWhere($where);

            // 查询数据
            $miniQrcodeList = $h5QrcodeList = [];
            $dataList = $this->model->with(['shopData'])->where($where)->where($whereIds)->select();
            if (count($dataList) > 100) {
                $this->error(__('单次最多支持下载100个点餐码'));
            }
            foreach ($dataList as $item) {
                $qrcodeName = $item->shopData['name'] . '-' . $item->number . ($item->note ? '-' . $item->note : '');
                // 小程序二维码
                if ($appId && $appSecret) {
                    $hasQrcode = false;
                    if ($item->mini_qrcode) {
                        if (is_file(ROOT_PATH . 'public' . $item->mini_qrcode)) {
                            $hasQrcode = true;
                        }
                    }
                    if (! $hasQrcode) {
                        try {
                            $params = ['did' => $item->id, 'sid' => $item->shop_id, 'number' => $item->number];
                            $miniQrcode = Qrcode::createMiniQrcode(Qrcode::PAGE_FOOD_HOME, http_build_query($params),
                                false);
                            // 合成图片
                            $item->mini_qrcode = $miniQrcode->src;
                            $item->save();
                        } catch (Exception $e) {
                            if (strpos($e->getMessage(), 'invalid page') !== false) {
                                $this->error(__('小程序新版本还未发布'));
                            }
                            $this->error(__($e->getMessage()));
                        }
                    }

                    // 小程序点餐码
                    $qrcodePath = ROOT_PATH . 'public' . $item->mini_qrcode;
                    $backPath = ROOT_PATH . 'public' . $item->shopData->desk_image;
                    $deskName = $item->number . ($item->note ? '-' . $item->note : '');
                    $deskImage = $this->createPoster($qrcodePath, $backPath, $deskName);
                    $miniQrcodeList[$deskImage] = $qrcodeName;
                }

                // H5二维码
                if ($h5Domain) {
                    $hasQrcode = false;
                    if ($item->h5_qrcode) {
                        if (is_file(ROOT_PATH . 'public' . $item->h5_qrcode)) {
                            $hasQrcode = true;
                        }
                    }
                    if (! $hasQrcode) {
                        try {
                            $params = ['did' => $item->id, 'sid' => $item->shop_id, 'number' => $item->number];
                            $content = trim($h5Domain, '/') . '/#/' . Qrcode::PAGE_FOOD_HOME;
                            $content .= '?scene=' . urlencode(http_build_query($params));
                            $normalQrcode = Qrcode::createNormalQrcode($content);
                            // 合成图片
                            $item->h5_qrcode = $normalQrcode->src;
                            $item->save();
                        } catch (Exception $e) {
                            $this->error(__($e->getMessage()));
                        }
                    }
                    // H5点餐码
                    $qrcodePath = ROOT_PATH . 'public' . $item->h5_qrcode;
                    $backPath = ROOT_PATH . 'public' . $item->shopData->desk_image;
                    $deskName = $item->number . ($item->note ? '-' . $item->note : '');
                    $deskImage = $this->createPoster($qrcodePath, $backPath, $deskName);
                    $h5QrcodeList[$deskImage] = $qrcodeName;
                }
            }

            $zip = new \ZipArchive();
            $zipFilename = ROOT_PATH . 'public/uploads/' . time() . '.zip';
            if ($zip->open($zipFilename, \ZipArchive::CREATE) !== true) {
                $this->error(__('无法创建压缩文件'));
            }
            foreach ($miniQrcodeList as $key => $value) {
                $zip->addFile($key, '小程序点餐码/' . $value . '.jpg');
            }
            foreach ($h5QrcodeList as $key => $value) {
                $zip->addFile($key, 'H5点餐码/' . $value . '.jpg');
            }
            $zip->close();

            // 设置响应头
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename="' . basename($zipFilename) . '"');
            header('Content-Length: ' . filesize($zipFilename));

            // 读取文件内容并发送到客户端
            readfile($zipFilename);
        }
    }

    protected function createPoster($qrcode, $backImage, $title)
    {
//        $qrcode = ROOT_PATH . 'public/assets/addons/yunfood/img/qrcode.jpg';  // 二维码路径
//        $backImage = ROOT_PATH . 'public/assets/addons/yunfood/img/desk_bg.png';  // 待合成的背景图路径
        $outFile = ROOT_PATH . 'public/uploads/' . uniqid('', true) . '.png';  // 合成后的图片输出路径

        // 图片合成
        $configPost = [
            // 要加上的图
            'image'      => [
                [
                    'url'     => $qrcode,
                    'left'    => 122, // 二维码距离左边像素
                    'top'     => 164, // 二维码距离上边像素
                    'stream'  => 0, // 图片资源是否是字符串图像流
                    'right'   => 0,
                    'bottom'  => 0,
                    'width'   => 360,
                    'height'  => 360,
                    'opacity' => 100
                ],
            ],
            'text'       => [
                [
                    'text'      => $title,
                    'align'     => 'center',
                    'top'       => 640,
                    'fontPath'  => ROOT_PATH . 'public/assets/fonts/SourceHanSansK-Regular.ttf',  // 字体文件
                    'fontSize'  => 30,          // 字号
                    'fontColor' => '0,0,0',   // 字体颜色
                    'angle'     => 0,
                ]
            ],
            //背景图
            'background' => $backImage
        ];
        Logic::createPoster($configPost, $outFile);

        return $outFile;
    }

    public function recyclebin()
    {
        return;
    }

    public function destroy($ids = null)
    {
        return;
    }

    public function restore($ids = null)
    {
        return;
    }
}
